package strategies

import (
	"context"
	"fmt"
	"math"

	"github.com/gogf/gf/v2/os/gtime"

	"goldtree/internal/strategy"
)

// MAStrategy 移动平均线策略
type MAStrategy struct {
	*strategy.BaseStrategy
	shortPeriod  int               // 短期均线周期
	longPeriod   int               // 长期均线周期
	priceData    map[string][]float64 // 价格数据缓存
	shortMA      map[string][]float64 // 短期均线数据
	longMA       map[string][]float64 // 长期均线数据
	lastSignals  map[string]strategy.SignalType // 最后信号
}

// NewMAStrategy 创建移动平均线策略
func NewMAStrategy() strategy.Strategy {
	return &MAStrategy{
		BaseStrategy: strategy.NewBaseStrategy(),
		priceData:    make(map[string][]float64),
		shortMA:      make(map[string][]float64),
		longMA:       make(map[string][]float64),
		lastSignals:  make(map[string]strategy.SignalType),
	}
}

// GetInfo 获取策略信息
func (s *MAStrategy) GetInfo() *strategy.StrategyInfo {
	return &strategy.StrategyInfo{
		Name:        "移动平均线策略",
		Version:     "1.0.0",
		Description: "基于短期和长期移动平均线的金叉死叉策略",
		Author:      "GoldTree",
		Parameters: []*strategy.ParameterDef{
			{
				Name:         "short_period",
				Type:         "int",
				DefaultValue: 5,
				MinValue:     1,
				MaxValue:     50,
				Description:  "短期均线周期",
				Required:     true,
			},
			{
				Name:         "long_period",
				Type:         "int",
				DefaultValue: 20,
				MinValue:     2,
				MaxValue:     200,
				Description:  "长期均线周期",
				Required:     true,
			},
			{
				Name:         "min_volume",
				Type:         "int",
				DefaultValue: 100000,
				MinValue:     0,
				Description:  "最小成交量过滤",
				Required:     false,
			},
		},
		RequiredData: []string{"kline", "volume"},
	}
}

// Initialize 初始化策略
func (s *MAStrategy) Initialize(ctx context.Context, config *strategy.StrategyConfig) error {
	// 调用基类初始化
	if err := s.BaseStrategy.Initialize(ctx, config); err != nil {
		return err
	}
	
	// 解析策略参数
	params := config.Parameters
	if shortPeriod, ok := params["short_period"].(float64); ok {
		s.shortPeriod = int(shortPeriod)
	} else {
		s.shortPeriod = 5 // 默认值
	}
	
	if longPeriod, ok := params["long_period"].(float64); ok {
		s.longPeriod = int(longPeriod)
	} else {
		s.longPeriod = 20 // 默认值
	}
	
	// 验证参数
	if s.shortPeriod >= s.longPeriod {
		return fmt.Errorf("短期均线周期必须小于长期均线周期")
	}
	
	if s.shortPeriod <= 0 || s.longPeriod <= 0 {
		return fmt.Errorf("均线周期必须大于0")
	}
	
	return nil
}

// OnMarketData 处理市场数据
func (s *MAStrategy) OnMarketData(ctx context.Context, data *strategy.MarketData) ([]*strategy.Signal, error) {
	// 更新价格数据
	s.updatePriceData(data.StockCode, data.ClosePrice)
	
	// 计算移动平均线
	shortMA := s.calculateMA(data.StockCode, s.shortPeriod, true)
	longMA := s.calculateMA(data.StockCode, s.longPeriod, false)
	
	// 检查是否有足够的数据
	if shortMA == 0 || longMA == 0 {
		return nil, nil // 数据不足
	}
	
	// 生成交易信号
	signals := s.generateSignals(ctx, data, shortMA, longMA)
	
	return signals, nil
}

// OnKLineData 处理K线数据
func (s *MAStrategy) OnKLineData(ctx context.Context, kline *strategy.KLineData) ([]*strategy.Signal, error) {
	// 转换为市场数据格式
	marketData := &strategy.MarketData{
		StockCode:   kline.StockCode,
		Price:       kline.ClosePrice,
		Volume:      kline.Volume,
		Timestamp:   kline.Timestamp,
		OpenPrice:   kline.OpenPrice,
		HighPrice:   kline.HighPrice,
		LowPrice:    kline.LowPrice,
		ClosePrice:  kline.ClosePrice,
		Change:      kline.Change,
		ChangeRatio: kline.ChangeRatio,
	}
	
	return s.OnMarketData(ctx, marketData)
}

// Validate 验证策略配置
func (s *MAStrategy) Validate(config *strategy.StrategyConfig) error {
	params := config.Parameters
	
	// 验证短期周期
	if shortPeriod, ok := params["short_period"]; ok {
		if period, ok := shortPeriod.(float64); !ok || period <= 0 || period > 50 {
			return fmt.Errorf("短期均线周期必须是1-50之间的整数")
		}
	}
	
	// 验证长期周期
	if longPeriod, ok := params["long_period"]; ok {
		if period, ok := longPeriod.(float64); !ok || period <= 0 || period > 200 {
			return fmt.Errorf("长期均线周期必须是1-200之间的整数")
		}
	}
	
	// 验证周期关系
	if shortPeriod, ok1 := params["short_period"].(float64); ok1 {
		if longPeriod, ok2 := params["long_period"].(float64); ok2 {
			if shortPeriod >= longPeriod {
				return fmt.Errorf("短期均线周期必须小于长期均线周期")
			}
		}
	}
	
	return nil
}

// updatePriceData 更新价格数据
func (s *MAStrategy) updatePriceData(stockCode string, price float64) {
	// 初始化数据
	if _, exists := s.priceData[stockCode]; !exists {
		s.priceData[stockCode] = make([]float64, 0)
		s.shortMA[stockCode] = make([]float64, 0)
		s.longMA[stockCode] = make([]float64, 0)
	}
	
	// 添加新价格
	s.priceData[stockCode] = append(s.priceData[stockCode], price)
	
	// 保持数据窗口大小
	maxLength := s.longPeriod * 2 // 保留更多历史数据
	if len(s.priceData[stockCode]) > maxLength {
		s.priceData[stockCode] = s.priceData[stockCode][len(s.priceData[stockCode])-maxLength:]
	}
}

// calculateMA 计算移动平均线
func (s *MAStrategy) calculateMA(stockCode string, period int, isShort bool) float64 {
	prices := s.priceData[stockCode]
	if len(prices) < period {
		return 0 // 数据不足
	}
	
	// 计算简单移动平均
	sum := 0.0
	start := len(prices) - period
	for i := start; i < len(prices); i++ {
		sum += prices[i]
	}
	ma := sum / float64(period)
	
	// 保存均线数据
	if isShort {
		s.shortMA[stockCode] = append(s.shortMA[stockCode], ma)
		if len(s.shortMA[stockCode]) > 100 {
			s.shortMA[stockCode] = s.shortMA[stockCode][1:]
		}
	} else {
		s.longMA[stockCode] = append(s.longMA[stockCode], ma)
		if len(s.longMA[stockCode]) > 100 {
			s.longMA[stockCode] = s.longMA[stockCode][1:]
		}
	}
	
	return ma
}

// generateSignals 生成交易信号
func (s *MAStrategy) generateSignals(ctx context.Context, data *strategy.MarketData, shortMA, longMA float64) []*strategy.Signal {
	var signals []*strategy.Signal
	
	// 获取历史MA数据用于判断趋势
	shortMAList := s.shortMA[data.StockCode]
	longMAList := s.longMA[data.StockCode]
	
	if len(shortMAList) < 2 || len(longMAList) < 2 {
		return nil // 需要更多历史数据
	}
	
	// 获取前一个时刻的MA值
	prevShortMA := shortMAList[len(shortMAList)-2]
	prevLongMA := longMAList[len(longMAList)-2]
	
	// 判断金叉和死叉
	var signalType strategy.SignalType
	var reason string
	var confidence float64
	
	// 金叉：短期均线从下方穿越长期均线
	if prevShortMA <= prevLongMA && shortMA > longMA {
		signalType = strategy.SignalBuy
		reason = fmt.Sprintf("金叉信号：短期MA(%.2f)上穿长期MA(%.2f)", shortMA, longMA)
		confidence = s.calculateConfidence(data, shortMA, longMA, true)
	} else if prevShortMA >= prevLongMA && shortMA < longMA {
		// 死叉：短期均线从上方穿越长期均线
		signalType = strategy.SignalSell
		reason = fmt.Sprintf("死叉信号：短期MA(%.2f)下穿长期MA(%.2f)", shortMA, longMA)
		confidence = s.calculateConfidence(data, shortMA, longMA, false)
	} else {
		// 无信号
		return nil
	}
	
	// 检查是否重复信号
	lastSignal, exists := s.lastSignals[data.StockCode]
	if exists && lastSignal == signalType {
		return nil // 避免重复信号
	}
	
	// 创建信号
	signal := &strategy.Signal{
		StrategyID: s.GetContext().Config.ID,
		StockCode:  data.StockCode,
		SignalType: signalType,
		Price:      data.Price,
		Quantity:   s.calculateQuantity(data),
		Confidence: confidence,
		Reason:     reason,
		Timestamp:  gtime.Now(),
		ExtraData: map[string]interface{}{
			"short_ma": shortMA,
			"long_ma":  longMA,
			"volume":   data.Volume,
		},
	}
	
	signals = append(signals, signal)
	
	// 记录最后信号
	s.lastSignals[data.StockCode] = signalType
	
	return signals
}

// calculateConfidence 计算信号置信度
func (s *MAStrategy) calculateConfidence(data *strategy.MarketData, shortMA, longMA float64, isBuy bool) float64 {
	// 基础置信度
	baseConfidence := 0.6
	
	// 根据MA差距调整置信度
	spread := math.Abs(shortMA - longMA)
	spreadRatio := spread / longMA
	
	// 差距越大，置信度越高
	confidenceBonus := math.Min(spreadRatio*2, 0.3)
	
	// 根据成交量调整
	volumeBonus := 0.0
	if data.Volume > 0 {
		// 这里可以根据历史平均成交量来判断
		// 简化处理：成交量越大，置信度稍微提升
		volumeBonus = 0.05
	}
	
	confidence := baseConfidence + confidenceBonus + volumeBonus
	
	// 限制在0-1范围内
	if confidence > 1.0 {
		confidence = 1.0
	}
	if confidence < 0.0 {
		confidence = 0.0
	}
	
	return confidence
}

// calculateQuantity 计算交易数量
func (s *MAStrategy) calculateQuantity(data *strategy.MarketData) int {
	// 简化处理：固定数量
	// 实际应用中应该根据仓位管理规则来计算
	baseQuantity := 100
	
	// 可以根据价格、市值等因素调整数量
	if data.Price > 100 {
		return baseQuantity // 高价股减少数量
	} else if data.Price > 50 {
		return baseQuantity * 2
	} else {
		return baseQuantity * 5 // 低价股增加数量
	}
}

// 注册策略
func init() {
	// 注册策略到管理器
	// strategy.GetManager().RegisterStrategy("ma", NewMAStrategy)
	
	// 注册参数配置
	configManager := strategy.GetConfigManager()
	params := []*strategy.ParameterConfig{
		{
			Name:         "short_period",
			Type:         strategy.ParamTypeInt,
			DefaultValue: 5,
			Required:     true,
			Description:  "短期均线周期",
			Label:        "短期周期",
			Group:        "基础参数",
			Order:        1,
			Validator:    &strategy.IntValidator{Min: intPtr(1), Max: intPtr(50)},
		},
		{
			Name:         "long_period",
			Type:         strategy.ParamTypeInt,
			DefaultValue: 20,
			Required:     true,
			Description:  "长期均线周期",
			Label:        "长期周期",
			Group:        "基础参数",
			Order:        2,
			Validator:    &strategy.IntValidator{Min: intPtr(2), Max: intPtr(200)},
		},
		{
			Name:         "min_volume",
			Type:         strategy.ParamTypeInt,
			DefaultValue: 100000,
			Required:     false,
			Description:  "最小成交量过滤",
			Label:        "最小成交量",
			Group:        "过滤条件",
			Order:        3,
			Validator:    &strategy.IntValidator{Min: intPtr(0)},
		},
	}
	
	configManager.RegisterParameterSchema("ma", params)
}

// 辅助函数
func intPtr(i int) *int {
	return &i
}